<?php
namespace zake\foundation\reactor\driver;

use zake\foundation\able\reactor\LoopAdaptAble;

/**
 * Class EventAdapt
 * @package zake\foundation\loop
 */
class EventAdapt implements LoopAdaptAble
{


    protected $_writeEventMap = [];

    protected $_readEventMap = [];

    protected $_timeEventMap = [];

    protected $_signalEventMap = [];

    /**
     *
     * @var int
     */
    private $_timeId = 0;


    /**
     *
     * @return static|EventAdapt|LoopAdaptAble
     *
     * @author liu.bin 2020-04-16 15:59
     */
    public static function create()
    {
        return new static();
    }

    protected $_eventBase = null;

    /**
     * 构造器
     *
     * Event constructor.
     */
    private function __construct()
    {
        $this->_eventBase = new \EventBase();
    }


    /**
     *
     * @author liu.bin 2020-03-26 13:23
     */
    public function loop()
    {
        $this->_eventBase->loop();
    }

    /**
     *
     * @param resource $resource
     *
     * @author
     */
    public function addRead($resource,\Closure $handler)
    {
        $event = new \Event(
            $this->_eventBase,
            $resource,
            \Event::READ | \Event::PERSIST,
            [$this,'readHandler'],
            $handler
        );
        $event->add();
        // 引用，防止垃圾回收
        $this->_readEventMap[(int)$resource] = $event;
    }

    public function addWrite($resource,\Closure $handler)
    {
        $event = new \Event(
            $this->_eventBase,
            $resource,
            \Event::WRITE | \Event::PERSIST,
            [$this,'writeHandler'],
            $handler
        );
        $event->add();
        // 引用，防止垃圾回收
        $this->_writeEventMap[(int)$resource] = $event;
    }


    public function addTime($interval, \Closure $handler, $param = [])
    {
        $timeId     = ++$this->_timeId;
        $type       = ($param['persistent']??true) ? (\Event::TIMEOUT|\Event::PERSIST) : \Event::TIMEOUT;
        $event = new \Event(
            $this->_eventBase,
            -1,
            $type,
            array($this, "timeHandler"),
            [$timeId,$handler]
        );
        $event->addTimer($interval);
        $this->_timeEventMap[$timeId] = $event;
        return $timeId;
    }


    /**
     * 添加信号处理
     * @param $sigNo
     * @param \Closure $handler
     *
     * @author liu.bin 2020-04-28 13:49
     */
    public function addSignal($sigNo, \Closure $handler)
    {
        $event = \Event::signal($this->_eventBase, $sigNo, $handler);
        $event->add();
        $this->_signalEventMap[$sigNo] = $event;
    }



    /**
     *
     * @param resource $resource
     * @return bool;
     * @author liu.bin 2020-04-15 21:58
     */
    public function removeRead($resource)
    {
        if(isset($this->_readEventMap[(int)$resource])){
            $this->_readEventMap[(int)$resource]->del();
            unset($this->_readEventMap[(int)$resource]);
        }
        return true;
    }


    public function removeWrite($resource)
    {
        if(isset($this->_writeEventMap[(int)$resource])){
            $this->_writeEventMap[(int)$resource]->del();
            unset($this->_writeEventMap[(int)$resource]);
        }
        return true;
    }


    public function removeTime($timeId)
    {
        if(isset($this->_timeEventMap[$timeId])){
            $this->_timeEventMap[$timeId]->del();
            unset($this->_timeEventMap[$timeId]);
        }
        return true;
    }


    /**
     * 移除信号监听
     * @param $sigNo
     *
     * @author liu.bin 2020-04-28 13:51
     */
    public function removeSignal($sigNo)
    {
        if (isset($this->_signalEventMap[$sigNo])) {
            $this->_signalEventMap[$sigNo]->del();
            unset($this->_signalEventMap[$sigNo]);
        }
    }


    /**
     * 读取数据
     * @param resource $resource
     * @param int $flag
     *
     * @author liu.bin 2020-04-15 17:11
     */
    public function readHandler($resource,$flag,\Closure $handler)
    {
        $handler();
    }


    /**
     * 执行发送数据的操作
     *
     * @param resource $resource
     * @param int $flag
     *
     * @author liu.bin 2020-04-15 17:21
     */
    public function writeHandler($resource,$flag,\Closure $handler)
    {
        $handler();
    }


    public function timeHandler($fd, $flag, $param)
    {
        list($timeId,$handler) = $param;
        $handler($timeId);
    }
}
